package com.labelimage.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.labelimage.bean.entity.ImageEntity;
import com.labelimage.bean.entity.LabelEntity;
import com.labelimage.bean.entity.LabelImageEntity;
import com.labelimage.bean.entity.TemplateEntity;
import com.labelimage.bean.param.TemplateParam;
import com.labelimage.bean.vo.DistributedVo;
import com.labelimage.dao.TemplateDao;
import com.labelimage.service.ImageService;
import com.labelimage.service.LabelImageService;
import com.labelimage.service.LabelService;
import com.labelimage.service.TemplateService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;


@Service("templateService")
@Transactional(rollbackFor = Exception.class)
public class TemplateServiceImpl extends ServiceImpl<TemplateDao, TemplateEntity> implements TemplateService {

    @Resource
    private LabelService labelService;
    @Resource
    private ImageService imageService;
    @Resource
    private LabelImageService labelImageService;

    @Override
    public void create(TemplateParam templateParam) {
        TemplateEntity templateEntity = new TemplateEntity();
        templateEntity.setTemplateName(templateParam.getTemplateName());
        templateEntity.setDatasetId(templateParam.getDatasetId());
        templateEntity.setTemplateDesc(templateParam.getTemplateDesc());
        templateEntity.setCreateUser(templateParam.getCreateUser());
        templateEntity.setCreateTime(new Date());
        this.save(templateEntity);

        templateParam.getLabelList().forEach(label -> {
            LabelEntity labelEntity = new LabelEntity();
            labelEntity.setLabelName(label);
            labelEntity.setTemplateId(templateEntity.getId());
            labelService.save(labelEntity);
        });
        imageService.lambdaQuery()
                .eq(ImageEntity::getDatasetId, templateParam.getDatasetId())
                .list()
                .forEach(imageEntity -> {
                    LabelImageEntity labelImageEntity = new LabelImageEntity();
                    labelImageEntity.setTemplateId(templateEntity.getId());
                    labelImageEntity.setImageId(imageEntity.getId());
                    labelImageService.save(labelImageEntity);
                });
    }

    @Override
    public void delete(Long templateId) {
        this.removeById(templateId);
        LambdaQueryWrapper<LabelEntity> labelEntityLambdaQueryWrapper = Wrappers.lambdaQuery();
        labelService.remove(labelEntityLambdaQueryWrapper.eq(LabelEntity::getTemplateId, templateId));
        LambdaQueryWrapper<LabelImageEntity> labelImageEntityLambdaQueryWrapper = Wrappers.lambdaQuery();
        labelImageService.remove(labelImageEntityLambdaQueryWrapper.eq(LabelImageEntity::getTemplateId, templateId));
    }

    @Override
    public List<DistributedVo> getDistributed(Long templateId) {
        Integer nullCount = labelImageService.lambdaQuery()
                .eq(LabelImageEntity::getTemplateId, templateId)
                .isNull(LabelImageEntity::getLabelId)
                .count();
        List<DistributedVo> distributedVoList = labelService.lambdaQuery()
                .eq(LabelEntity::getTemplateId, templateId)
                .list()
                .stream()
                .map(labelEntity -> {
                    DistributedVo distributedVo = DistributedVo.builder().build();
                    distributedVo.setType(labelEntity.getLabelName());
                    distributedVo.setValue(labelImageService.lambdaQuery()
                            .eq(LabelImageEntity::getTemplateId, templateId)
                            .eq(LabelImageEntity::getLabelId, labelEntity.getId())
                            .count());
                    return distributedVo;
                }).collect(Collectors.toList());
        distributedVoList.add(DistributedVo.builder()
                .type("未标签")
                .value(nullCount)
                .build());
        return distributedVoList;
    }
}